---
title: "Master / Detail - Detail Grids"
enterprise: true
---

When a row in the Master Grid is expanded, a new Detail Grid appears underneath that row. This page describes configuration options relevant to the Detail Grid.

This page explains how to configure the Detail Cell Renderer using the `detailCellRendererParams` Grid Option and how you can interact with the Detail Grids using the Master Grid's API.

The Detail Grid fits inside one row of the Master Grid without using any of the Master Grid's columns. It is the job of the Detail Cell Renderer to draw the Detail Grid into the provided detail row.

## Detail Grid Definition

The Detail Grid is a fully fledged independent grid instance. This means that the Detail Grid has access to the full range of grid features.

The Grid Options object is provided to the Detail Grid using the parameter `detailGridOptions`.

The example below shows configuring a Detail Grid with some additional Grid Options set. Note the following:

* The `detailGridOptions` is provided inside the `detailCellRendererParams`.
* The Detail Grid Options has the following properties set: `rowSelection={mode: 'multiRow', headerCheckbox: false}`, `pagination=true` and `paginationAutoPageSize=true`.
* The Detail Grid Options is provided with a Default Column Definition (`defaultColDef`) that makes all columns use Flex for sizing.

{% gridExampleRunner title="Detail Grid Options" name="grid-options" /%}

## Providing Rows

Row data is provided to the Detail Grid by implementing the `getDetailRowData` callback of the Detail Cell Renderer Params. The interface of this callback is as follows:

{% interfaceDocumentation interfaceName="IDetailCellRendererParams" names=["getDetailRowData"] config={"overrideBottomMargin":"1rem", "description": ""} /%}

The `successCallback` can be called immediately in a synchronous fashion (typical if the data is already available) or asynchronously at a later time (typical if the data needs to be fetched remotely).

The Master Grid in turn will call `api.setGridOption('rowData', data)` on the Detail Grid with the data provided.

Below shows an example using `setTimeout()` to delay supplying data to the detail row to simulate asynchronous loading of data in the detail.

{% gridExampleRunner title="Lazy Load Detail Rows" name="lazy-load-rows"  exampleHeight=550 /%}

## Dynamic Definitions

There will be many instances of Detail Grids within one Master Grid, as each time you expand a Master Row, a new Detail Grid instance is created. It is possible to dynamically create Detail Cell Renderer Params so each Detail Grid gets its own version of the params, allowing each Detail Grid to be configured differently.

This is done by providing a function to `detailCellRendererParams` that in turn returns the params to use for that Detail Grid.

Below shows an example of this, where the Detail Grids are configured with different columns. Note the following:

* Expanding rows 'Mila Smith' or 'Harper Johnson' will use a detail grid with the columns {Call ID, Number}.
* Expanding all other rows will use a detail grid with the columns {Call ID, Direction, Duration, Switch Code}.

{% gridExampleRunner title="Dynamic Params" name="dynamic-params" /%}

{% partial file="./_changing-the-template.mdoc" /%}

## Accessing Detail Grids

The Master Grid manages all the Detail Grid instances. You can access the API of the underlying Detail Grids to call API methods directly on those grids. The Master Grid stores references to the Detail Grid API's in Detail Grid Info objects.

The Detail Grid Info objects contain a reference to the underlying [Grid API](./grid-api/) for each detail grid. The interface for Detail Grid Info is as follows:

{% interfaceDocumentation interfaceName="DetailGridInfo" config={"description": ""} /%}

The Detail Grid Info objects are accessed via the Master Grid's API via the following methods:

{% apiDocumentation source="grid-api/api.json" section="masterDetail" names=["getDetailGridInfo"] /%}

```{% frameworkTransform=true %}
// lookup a specific DetailGridInfo by id, and then call flashCells() on it
const detailGridInfo = api.getDetailGridInfo('detail_someId');
detailGridInfo.api.flashCells();
```

The grid generates IDs for detail grids by prefixing the parent row's ID with `detail_{ROW-ID}`. For example if the ID of the expanded Master Row is `"88"`, then the ID of the Detail Grid / row will be `"detail_88"`.

{% apiDocumentation source="grid-api/api.json" section="masterDetail" names=["forEachDetailGridInfo"] /%}

```{% frameworkTransform=true %}
// iterate over all DetailGridInfos, and call flashCells() on each one
api.forEachDetailGridInfo(detailGridInfo => {
    detailGridInfo.api.flashCells();
});
```

The following example shows flashing cells on the detail grids by using the Grid API `flashCells()`. Note the following:

* The example is made more compact by a) setting Detail Row Height to 200 pixels and b) setting CSS to reduce padding around the Detail Grid.
* The callback `getRowId` is implemented in the Master Grid to give each row an ID. In this instance the `account` attribute is used.
* Button 'Flash Mila Smith' uses `getDetailGridInfo` to get access to the Grid API for the Mila Smith Detail Grid.
* Button 'Flash All' uses `forEachDetailGridInfo` to access all existing Detail Grids.

{% gridExampleRunner title="Detail Grid API" name="detail-grid-api"  exampleHeight=535 /%}

## Detail Grid Lifecycle

When a Master Row is expanded a Detail Row is created. When the Master Row is collapsed, the Detail Row is destroyed. When the Master Row is expanded a second time, a Detail Row is created again from scratch. This can be undesirable behaviour if there was context in the Detail Row, e.g. if the user sorted or filtered data in the Detail Row, the sort or filter will be reset the second time the Detail Row is displayed.

To prevent losing the context of Details Rows, the grid provides two properties to cache the Details Rows to be reused the next time the row is shown. The properties are as follows:

{% apiDocumentation source="grid-options/properties.json" section="masterDetail" names=["keepDetailRows", "keepDetailRowsCount"] /%}

The example below demonstrates keeping Detail Rows. Note the following:

* The Master Grid has property `keepDetailRows=true` to turn on keeping Detail Rows.
* The Master Grid has property `keepDetailRowsCount=2` which sets the number of Details Rows to keep to 2.
* All the Detail Grids allow moving and sorting columns. If you change the state of a Detail Grid (e.g. by sorting a Detail Grid), that state will be kept if you close the Parent Row and then open the Parent Row again.
* The maximum number of Detail Rows kept is two. If you open three Detail Rows and apply sorting on each Detail Grid, then close all three Detail Rows (so none are showing) and then open all three again, only two of them will have the sort state kept.

{% gridExampleRunner title="Keep Detail Rows" name="keep-detail-rows"  exampleHeight=565 /%}

## Detail Parameters

<!-- Below we don't show 'template' for React, hence listing the properties twice -->

{% if isFramework("javascript", "angular", "vue") %}
{% interfaceDocumentation interfaceName="IDetailCellRendererParams" names=["detailGridOptions", "getDetailRowData", "template", "refreshStrategy"] /%}
{% /if %}

{% if isFramework("react") %}
{% interfaceDocumentation interfaceName="IDetailCellRendererParams" names=["detailGridOptions", "getDetailRowData", "refreshStrategy"] /%}
{% /if %}

The pattern of setting components such as Cell Renderers and providing parameters to those components is consistent across the grid and explained in [Grid Components](./components/).

As with all components, the parameters object (in this case `detailCellRendererParams`) can either be an Object, or it can be a function that returns an Object. The latter allows providing different parameters for each Detail Grid, allowing Detail Grids to be configured differently.

## Styling Detail Grids

Detail grids must have the same theme as their master grid, but you can use CSS to change the style of the detail grid. See [Master / Detail Styling](./theming-master-detail/) for more details.

## Row Selection
By default, selecting rows in the Master Grid has no effect on any of the Detail Grids. In order to have the selection state of the Master Grid be reflected in the Detail Grids (and vice-versa), users should use the `rowSelection.masterSelects` grid option:

```{% frameworkTransform=true %}
const gridOptions = {
    rowSelection: { 
        mode: 'multiRow',
        masterSelects: 'detail',
    }
}
```

In the example below, selecting a master row will select all rows in the associated detail grid. Similarly, selecting all rows in the detail grid will select the master row. When only some rows in the detail grid are selected, the master row will have the indeterminate state.

{% gridExampleRunner title="Row Selection" name="row-selection"  exampleHeight=550 /%}

Note that selecting a master row will select _all_ rows in the detail grid, regardless of the value of `rowSelection.selectAll` in the `detailGridOptions`.

Note also that calling the API methods `getSelectedNodes` and `getSelectedRows` on the master grid will not return any information about the selection states of any detail grids.

## Next Up

Continue to the next section to learn about [Master / Detail - Detail Height](./master-detail-height/).
